#ifndef LW_HASH_MAP_H
#define LW_HASH_MAP_H

#include <hash_map>
#include <string>

template<typename KeyType, typename ValueType>
class HashMap {
protected:
	stdext::hash_map<KeyType, ValueType> wrappedHashMap;
	static const std::string valueNotFoundMessage;

public:
	HashMap() {
		
	}

	virtual ~HashMap() {

	}

    /**
     * Compares specified hashmap with this hashmap and returns true if they are equal.
     */
	virtual inline bool operator==(const HashMap& v) const {
		return (wrappedHashMap == v.wrappedHashMap);
	}

    /**
     * Compares specified hashmap with this hashmap and returns true if they are not equal.
     */
	virtual inline bool operator!=(const HashMap& v) const {
		return (wrappedHashMap != v.wrappedHashMap);
	}

    /**
	 * Puts the specified value associated with the specified key into this hashmap.
	 */
	virtual inline void Put(const KeyType& key, const ValueType& value) {
		wrappedHashMap[key] = value;
	}

    /**
	 * Returns a reference to the value that is associated with the specified key.
	 * If no value is found for this key, an exception is thrown.
	 */
	virtual inline ValueType& Get(const KeyType& key) {
		if(wrappedHashMap.count(key) > 0) {
			return wrappedHashMap[key];
		}

		throw std::runtime_error(valueNotFoundMessage);
	}

	/**
	 * Removes the value associated with the specified key from this hashmap.
	 * If no value is found, does nothing.
	 */
	virtual inline void Remove(const KeyType& key) {
		wrappedHashMap.erase(key);
	}

	/**
	 * Removes all values from this hashmap.
	 */
	virtual inline void Clear() {
		wrappedHashMap.clear();
	}

	/**
	 * Returns the number of values in this hashmap.
	 */
	virtual inline int Size() const {
		return wrappedHashMap.size();
	}

	/**
	 * Returns true if this hashmap has no values.
	 */
	virtual inline bool Empty() const {
		return wrappedHashMap.empty();
	}

	/**
	 * Returns the number of values that are assiciated with the specified key. 
	 */
	virtual inline int Count(const KeyType& key) {
		return wrappedHashMap.count(key);
	}

	/**
	 * Returns true if this hashmap has a value that is associated with the specified key.
	 */
	virtual inline bool Exist(const KeyType& key) {
		return (wrappedHashMap.count(key) > 0);
	}
};

template<typename KeyType, typename ValueType>
const std::string HashMap<KeyType, ValueType>::valueNotFoundMessage = "HashMap (stdext::hash_map) value not found";

#endif //LW_HASH_MAP_H
